################################################################################
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
################################################################################

#MAKEDBG = 1		# uncomment for exhaustive variable reports

################################################################################
# HARDWARE CONFIGURATION
################################################################################
TOOLING_PREFIX = arm-none-eabi-
TARGET_TYPE    = -mcpu=cortex-m4
TARGET_FPU     = -mfpu=fpv4-sp-d16
TARGET_FAPI    = -mfloat-abi=hard
TARGET_MCU     = STM32L476xx
ifdef MAKEDBG
$(info TOOLING_PREFIX is '$(TOOLING_PREFIX)'.)
$(info TARGET_TYPE    is '$(TARGET_TYPE)'.)
$(info TARGET_FPU     is '$(TARGET_FPU)'.)
$(info TARGET_FAPI    is '$(TARGET_FAPI)'.)
endif

################################################################################
# BUILD CONFIGURATION
################################################################################

DRIVERS_PATH          := ./drivers
DRIVERS_SOURCE_FILES  := $(wildcard $(DRIVERS_PATH)/*.c)
STARTUP_PATH          := $(DRIVERS_PATH)/GCC
STARTUP_SOURCE_FILES  := $(wildcard $(STARTUP_PATH)/*.s)
LINKER_SCRIPT         := $(wildcard $(STARTUP_PATH)/*.ld)
BSP_SOURCE_PATH       := ./src
BSP_SOURCE_FILES      := $(wildcard $(BSP_SOURCE_PATH)/*.c)
BSP_INCLUDE_PATH      := ./include
TEST_PATH             := ../../../test
TEST_SOURCE_FILES     := $(wildcard $(TEST_PATH)/*.c)
ALL_SOURCE_FILES      := $(DRIVERS_SOURCE_FILES) $(STARTUP_SOURCE_FILES) $(BSP_SOURCE_FILES) $(TEST_SOURCE_FILES)
ifdef MAKEDBG
$(info DRIVERS_PATH          is '$(DRIVERS_PATH)'.)
$(info DRIVERS_SOURCE_FILES  is '$(DRIVERS_SOURCE_FILES)'.)
$(info STARTUP_PATH          is '$(STARTUP_PATH)'.)
$(info STARTUP_SOURCE_FILES  is '$(STARTUP_SOURCE_FILES)'.)
$(info LINKER_SCRIPT         is '$(LINKER_SCRIPT)'.)
$(info BSP_SOURCE_PATH       is '$(BSP_SOURCE_PATH)'.)
$(info BSP_SOURCE_FILES      is '$(BSP_SOURCE_FILES)'.)
$(info BSP_INCLUDE_PATH      is '$(BSP_INCLUDE_PATH)'.)
$(info TEST_PATH             is '$(TEST_PATH)'.)
$(info TEST_SOURCE_FILES     is '$(TEST_SOURCE_FILES)'.)
$(info ALL_SOURCE_FILES      is '$(ALL_SOURCE_FILES)'.)
endif

BUILD_ROOT           := ./build
DRIVERS_OBJECT_FILES := $(addprefix $(BUILD_ROOT)/, $(notdir $(addsuffix .o, $(basename $(DRIVERS_SOURCE_FILES)))))
STARTUP_OBJECT_FILES := $(addprefix $(BUILD_ROOT)/, $(notdir $(addsuffix .o, $(basename $(STARTUP_SOURCE_FILES)))))
BSP_OBJECT_FILES     := $(addprefix $(BUILD_ROOT)/, $(notdir $(addsuffix .o, $(basename $(BSP_SOURCE_FILES)))))
TEST_OBJECT_FILES    := $(addprefix $(BUILD_ROOT)/, $(notdir $(addsuffix .o, $(basename $(TEST_SOURCE_FILES)))))
OBJECT_FILES         := $(DRIVERS_OBJECT_FILES) $(STARTUP_OBJECT_FILES) $(BSP_OBJECT_FILES) $(TEST_OBJECT_FILES)
ASSEMBLER_FILES      := $(addsuffix .s, $(basename $(OBJECT_FILES)))
ifdef MAKEDBG
$(info BUILD_ROOT           is '$(BUILD_ROOT)'.)
$(info DRIVERS_OBJECT_FILES is '$(DRIVERS_OBJECT_FILES)'.)
$(info BSP_OBJECT_FILES     is '$(BSP_OBJECT_FILES)'.)
$(info TEST_OBJECT_FILES    is '$(TEST_OBJECT_FILES)'.)
$(info OBJECT_FILES         is '$(OBJECT_FILES)'.)
$(info ASSEMBLER_FILES      is '$(ASSEMBLER_FILES)'.)
endif

TOOLS_INCLUDE_PATH := ../../../tools
COROS_INCLUDE_PATH := ../../../include
COROS_LIB_PATH     := ../../../lib
COROS_LIB          := $(COROS_LIB_PATH)/libcoros_CORTEXM4F.a
COROS_LIB_NAME     := coros_CORTEXM4F
ALL_INCLUDE_PATHS  := $(DRIVERS_PATH) $(BSP_INCLUDE_PATH) $(TEST_PATH) $(TOOLS_INCLUDE_PATH) $(COROS_INCLUDE_PATH)
ifdef MAKEDBG
$(info TOOLS_INCLUDE_PATH is '$(TOOLS_INCLUDE_PATH)'.)
$(info COROS_INCLUDE_PATH is '$(COROS_INCLUDE_PATH)'.)
$(info COROS_LIB_PATH     is '$(COROS_LIB_PATH)'.)
$(info COROS_LIB          is '$(COROS_LIB_PATH)'.)
$(info COROS_LIB_NAME     is '$(COROS_LIB_NAME)'.)
$(info ALL_INCLUDE_PATHS  is '$(ALL_INCLUDE_PATHS)'.)
endif

TARGET := $(BUILD_ROOT)/coros-test.out
TARGET_BIN := $(addsuffix .bin, $(basename $(TARGET)))
TARGET_HEX := $(addsuffix .hex, $(basename $(TARGET)))
TARGET_MAP := $(addsuffix .map, $(basename $(TARGET)))
TARGET_SYM := $(addsuffix .sym, $(basename $(TARGET)))
ifdef MAKEDBG
$(info TARGET     is '$(TARGET)'.)
$(info TARGET_BIN is '$(TARGET_BIN)'.)
$(info TARGET_HEX is '$(TARGET_HEX)'.)
$(info TARGET_MAP is '$(TARGET_MAP)'.)
$(info TARGET_SYM is '$(TARGET_SYM)'.)
endif

################################################################################
# TOOL CONFIGURATION
################################################################################

CC      := $(TOOLING_PREFIX)gcc
CFLAGS  := -g -Os -Werror -Wall $(TARGET_TYPE) $(TARGET_FAPI) $(TARGET_FPU)
CFLAGS  += -D $(TARGET_MCU) $(addprefix -I , $(ALL_INCLUDE_PATHS)) -MMD -MP
CFLAGS  += -L $(COROS_LIB_PATH)
LD      := $(CC)
LFLAGS  := $(CFLAGS) --specs=nosys.specs -T $(LINKER_SCRIPT) -Wl,-Map=$(TARGET_MAP) -Wl,--cref -Wl,--wrap=main
LFLAGS2 := -lc -lm -l$(COROS_LIB_NAME)
TOBIN   := $(TOOLING_PREFIX)objcopy -O binary
TOHEX   := $(TOOLING_PREFIX)objcopy -O ihex
TOSYM   := nm -f sysv -n -g
ifdef MAKEDBG
$(info CC      is '$(CC)'.)
$(info CFLAGS  is '$(CFLAGS)'.)
$(info LD      is '$(LD)'.
$(info LFLAGS  is '$(LFLAGS)'.)
$(info LFLAGS2 is '$(LFLAGS2)'.)
$(info TOBIN   is '$(TOBIN)'.)
$(info TOHEX   is '$(TOHEX)'.)
$(info TOSYM   is '$(TOSYM)'.)
endif

################################################################################
# BOOKKEEPING RULES
################################################################################

.PHONY : targets
targets :
	-@echo Targets: all force clean

.PHONY : all
all : $(TARGET)

.PHONY: force
force: clean all

.PHONY : clean
clean :
	-@rm -fRv $(BUILD_ROOT)

################################################################################
# RECIPES
################################################################################

$(TARGET) : $(OBJECT_FILES) $(COROS_LIB) $(LINKER_SCRIPT)
	-@mkdir -p $(BUILD_ROOT)
	$(LD) $(LFLAGS) -o $@ $(OBJECT_FILES) $(LFLAGS2)
	$(TOBIN) $@ $(TARGET_BIN)
	$(TOHEX) $@ $(TARGET_HEX)
	$(TOSYM) $@ > $(TARGET_SYM)

$(BUILD_ROOT)/%.o : $(DRIVERS_PATH)/%.c
	-@mkdir -p $(BUILD_ROOT)
	$(CC) $(CFLAGS) -S $< -o $(BUILD_ROOT)/$*.s
	$(CC) $(CFLAGS) -c $< -o $(BUILD_ROOT)/$*.o

$(BUILD_ROOT)/%.o : $(STARTUP_PATH)/%.s
	-@mkdir -p $(BUILD_ROOT)
	$(CC) $(CFLAGS) -c $< -o $(BUILD_ROOT)/$*.o

$(BUILD_ROOT)/%.o : $(BSP_SOURCE_PATH)/%.c
	-@mkdir -p $(BUILD_ROOT)
	$(CC) $(CFLAGS) -S $< -o $(BUILD_ROOT)/$*.s
	$(CC) $(CFLAGS) -c $< -o $(BUILD_ROOT)/$*.o

$(BUILD_ROOT)/%.o : $(TEST_PATH)/%.c
	-@mkdir -p $(BUILD_ROOT)
	$(CC) $(CFLAGS) -S $< -o $(BUILD_ROOT)/$*.s
	$(CC) $(CFLAGS) -c $< -o $(BUILD_ROOT)/$*.o

################################################################################
# BUILD RULES
################################################################################

$(TARGET_LIB) : $(TARGET_OBJECT_FILES)

################################################################################
# FORCE REBUILD ON MAKEFILE CHANGE
################################################################################

-include marker
marker: Makefile
	@touch $@
	$(MAKE) clean

-include $(BUILD_ROOT)/*.d
